package com.sky.aop;


import com.sky.annotation.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.time.LocalDateTime;

/**
 *  自定义注解的切片类，负责执行公共字段的自动填充
 */

@Aspect
@Component
public class AutoFillAOP {
    //1、定义切点
    @Pointcut("execution(* com.sky.mapper.*.*(..)) " +
            "&& @annotation(com.sky.annotation.AutoFill)")
    public void autoFillPointCut(){

    };

    //切片执行
    @Before("autoFillPointCut()")
    public void autoFill(JoinPoint joinPoint) {
        //1 通过joinPoint获得对应方法的名字
        //建议使用子类：MethodSignature，方法多
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();

        //2 获得具体打标记的方法
        AutoFill annotation = signature.getMethod().getAnnotation(AutoFill.class);

        //3、获得注解的枚举类属性值，判断是哪一种操作
        OperationType value = annotation.value();

        //4、获得反射方法的参数
        Object[] args = joinPoint.getArgs();

        //5、通过数组获得实体类参数，所以一般都是用在MAPPER层
        Object entity = args[0];
        LocalDateTime time = LocalDateTime.now();
        Long id = BaseContext.getCurrentId();
        try {
            if(value == OperationType.INSERT){
                //6、获得反射对象的set方法

                    Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
                    Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);

                    Method scu = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
                    Method suu = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);

                    setCreateTime.invoke(entity, time);
                    setUpdateTime.invoke(entity, time);
                    scu.invoke(entity, id);
                    suu.invoke(entity, id);
            }else if(value == OperationType.UPDATE){
                Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                Method suu = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
                setUpdateTime.invoke(entity, time);
                suu.invoke(entity, id);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}
